import math
from math import *

import pyglet
from pyglet.window import key, mouse
from pyglet.gl import *
from pyglet import gl

import cocos
from cocos.actions import *
from cocos.layer import *
from cocos.scene import *
from cocos.sprite import *
from cocos.director import director
from cocos.scenes.transitions import *
from cocos.euclid import Point2
from cocos.draw import *
from cocos.text import *

import Box2D as box2d

from globalvars import *
import ui
import listener 
from res import Images

###--------------------------###       
#        
#    GameWorld
#
###---------------------------### 

class GameWorld(ColorLayer, box2d.b2World):
    """
    GameWorld handles 
    - Entities
    - Rendering with cocos.layer.ColorLayer
    - Physics world with box2d.b2World,
    - Physics contacts with GameContactListener and GameContactPoint
    """
    
    is_event_handler = True
    
    DT = 1.0/60.0
    VEL_ITERS = 10
    POS_ITERS = 8
    
    ZOOM_STEP = 0.04
    DEFAULT_ZOOM = 0.3
    viewZoom = None
    isPaused = None
    
    def __init__(self):
        "Cocos2d and gameplay related"
        ColorLayer.__init__(self,255,255,255,0)#,1000,1000)
        self.scale = self.DEFAULT_ZOOM
        self.sprites = self.children # merely a pointer
        self.isPaused = False
        
        "entity"
        self.entities = {}
        
        "box2d world init"
        worldAABB=box2d.b2AABB()
        worldAABB.lowerBound = (-500, -500.0)
        worldAABB.upperBound = ( 500.0, 500.0)
        box2d.b2World.__init__(self, worldAABB, (0,0), True)
        self.gravity = (0,0)
        
        "The listeners"
        self.points = []
        self.contactListener = listener.GameContactListener()
        self.contactListener.test = self
        self.SetContactListener(self.contactListener)
        #self.debugDraw = listener.GameDebugDraw()
        #self.debugDraw.surface = director.window.screen
        #self.SetDebugDraw(self.debugDraw)
#        "The map"
#        self.map = Map1(self)
#        self.playerBox = self.map.playerBox
#        self.add(self.map,z=-1)

        
        
    def on_update(self,dt):
        "Update sprites, contact listener, world"
        pass#self.parent.gameHUD.update(dt)
#        
#        for entity in self.entities.values():
#            entity.update(dt)
#        
#        self.followPlayerBox()
#        self.points = []
#        self.Step(self.DT, self.VEL_ITERS, self.POS_ITERS)
#        self.Validate()
        #self.updateProjection()
        
    def on_key_press(self, symbol, modifiers):
        "Open pause menu"
        if symbol == key.ESCAPE:
            self.parent.on_pause()
            return True
    

    def on_mouse_scroll(self, x, y, dx, dy):
        self.scale += dy*self.ZOOM_STEP
       
    def on_activate(self):
        "continue update if window is active"
        pyglet.clock.unschedule(self.on_update)
        pyglet.clock.schedule_interval(self.on_update, self.DT)
        
    def on_deactivate(self):
        "pause update if window is inactive"
        pyglet.clock.unschedule(self.on_update)

    def addEntity(self,newEntity,*args,**kwargs):
        "Add an entity"
        self.entities[newEntity.id] = newEntity
        self.add(newEntity,*args,**kwargs)
        
    def removeEntity(self,idOrEntity):
        "Remove entity given itself or its ID"
        if type(idOrEntity) == int:
            ent = self.getEntityByID(idOrEntity)
            self.remove(ent)
            del self.entities[idOrEntity]
            #del ent
        else:
            id = self.getIDByEntity(idOrEntity)
            self.remove(idOrEntity)
            del self.entities[id]
            #del idOrEntity
        
    def getEntityByID(self,id):
        return self.entities[idOrEntity]
        
    def getIDByEntity(self,entity):
        return ([k for k, v in self.entities.iteritems() if v == entity][0])
###--------------------------###       
#        
#    GameHUD
#
###---------------------------### 

class GameHUD(ColorLayer):
    "Status report- headsup display"
    def __init__(self):
        "Init"
        ColorLayer.__init__(self,255,255,255,0)
        self.winSize = director.window.get_size()
        #self.scale = 1
        #self.offset = box2d.b2Vec2(-260,-160)
        self.playerBox = None
        


class GameScene(Scene):
    "Game Scene"
    
    def __init__(self):
        Scene.__init__(self)
        self.menuOverlay = None
        
        self.gameWorld = GameWorld()
        self.gameHUD = GameHUD()
        #self.gameHUD.setPlayerBox(self.gameWorld.playerBox)
        
        self.add(self.gameHUD, z=3)
        self.add(self.gameWorld, z=2)
        
        self.schedule_interval(self.gameWorld.on_update, self.gameWorld.DT)
        
    def on_pause(self):
        self.gameWorld.isPaused = True
        pyglet.clock.unschedule(self.gameWorld.on_update)
        self.menuOverlay = ui.MenuOverlay(self.gameWorld.isPaused)
        self.add(self.menuOverlay,z=4)
        self.menuOverlay.bg.image.opacity = 0
        self.menuOverlay.bg.image.do(FadeIn(0.2))
        
    def on_resume(self):
        self.gameWorld.isPaused = False
        pyglet.clock.schedule_interval(self.gameWorld.on_update, self.gameWorld.DT)
        self.remove(self.menuOverlay)
        self.menuOverlay = None
        
    def on_end_game(self):
        self.remove(self.menuOverlay)
        self.menuOverlay = None
        director.set_projection()
        director.replace(ZoomTransition(ui.MenuScene(), duration=0.3))
        
    


